const jwt = require("jsonwebtoken");

const errorType = require("../constants/error-types");
const userService = require("../service/user.service");
const authService = require("../service/auth.service");
const md5Password = require("../utils/password-handler");

// 公钥
const { PUBLIC_KEY } = require("../config/config");

const verifyLogin = async (ctx, next) => {
	// 获取用户名和密码
	const { name, password } = ctx.request.body;

	// 判断用户是否不存在
	const result = await userService.getUserByName(name);
	const user = result[0];
	if (!user) {
		const error = new Error(errorType.USER_DOES_NOT_EXISTS);
		return ctx.app.emit("error", error, ctx);
	}

	// 判断密码是否一致(加密)
	if (md5Password(password) !== user.password) {
		const error = new Error(errorType.PASSWORD_IS_INCORRENT);
		return ctx.app.emit("error", error, ctx);
	}

	ctx.user = user;

	await next();
};

// 验证是否有 token 授权
const verifyAuth = async (ctx, next) => {
	// 获取 token
	const authorization = ctx.headers.authorization;
	if (!authorization) {
		const error = new Error(errorType.UNAUTHORIZATION);
		return ctx.app.emit("error", error, ctx);
	}
	const token = authorization.replace("Bearer ", "");

	// 验证 token
	try {
		const result = jwt.verify(token, PUBLIC_KEY, {
			algorithms: ["RS256"]
		});

		ctx.user = result;

		await next();
	} catch (err) {
		const error = new Error(errorType.UNAUTHORIZATION);
		ctx.app.emit("error", error, ctx);
	}
};

// 验证用户是否具备权限
const verifyPerm = async (ctx, next) => {
	// 获取用户id
	const user_id = ctx.user.id;
	// 获取资源id
	const [key] = Object.keys(ctx.params);
	const resourceId = ctx.params[key];
	// 获取资源名
	const resourceName = key.replace("Id", "");

	// 查询权限
	try {
		const isPerm = await authService.checkResource(
			resourceName,
			resourceId,
			user_id
		);

		if (!isPerm) throw new Error();

		await next();
	} catch (err) {
		const error = new Error(errorType.UNPERMISSION);
		return ctx.app.emit("error", error, ctx);
	}
};

module.exports = {
	verifyLogin,
	verifyAuth,
	verifyPerm
};
